<template>
	<div class="dag-layout">
		<!-- 左侧节点列表 -->
		<stencil v-if="graph" />

		<div class="graph-container-box">
			<div class="tool-bar">
				<h1 class="logo">
					<a href="" style="display:flex;align-items: center">
						<img src="@/assets/img/apple-touch-icon.png" alt="" />
						<span style="color:#000;margin-left:10px;font-size:20px">行为树开发平台</span>
					</a>
				</h1>
				<!-- <ul class="graph-handle">
					<li v-for="e in 9" :key="e" @click="action(e)" :class="`graph-handle-btn${e}`" />
				</ul> -->
				<div class="graph-handle">
					<ToolBar />
				</div>
				<el-button class="run-btn" type="primary" size="medium" icon="el-icon-caret-right" @click="run">运行</el-button>
				<!-- <el-button class="run-btn" type="primary" size="mini" icon="el-icon-caret-right" @click="saveDag">运行</el-button> -->
			</div>
			<div id="graph-container"></div>
			<!-- <div class="graph-mini-map"></div> -->
		</div>
		<div id="container">
			<h3 class="container-title">条件节点设置</h3>
			<p class="container-hint" v-if="!containerData.isShowContainer">请点击节点进行编辑</p>
			<container v-else />
		</div>
	</div>
</template>

<script>
import { mapState, mapActions } from "vuex";
import stencil from "./components/stencil/";
import container from "./components/container/";
import ToolBar from "./components/ToolBar/";
import { uploadFile } from "@/api/file";
import { Base64 } from "js-base64";
import { execCommandExperiment } from "@/api/gameExperiment";
export default {
	name: "EditorDag2",
	components: {
		stencil,
		container,
		ToolBar,
	},
	data() {
		return {
			imageNodes: null,
			experiment_id: this.$route.query.experiment_id, //模型开发的ID
			scale: 1,
		};
	},
	computed: mapState({
		modelShapes: (state) => state.dagStore.modelShapes,
		graph: (state) => state.dagStore.graph,
		containerData: (state) => state.dagStore.containerData,
	}),
	created() {},
	mounted() {
		console.log("experiment_id", this.experiment_id);
		this.$nextTick(() => {
			this.init();

			// document.querySelector(".x6-graph-svg-viewport").addEventListener("mousewheel", this.handlerWheel);
			// document.querySelector(".x6-graph-svg-viewport").style.transform = `scale(${this.scale})`
		});
	},
	beforeDestroy() {},
	methods: {
		...mapActions(["getModelShapes", "assignGraph", "optForNode", "unOptForNode"]),
		init() {
			this.assignGraph("graph-container");

			this.bindingEvent();
			this.bindKey();

			// #region 初始化图形
		},
		bindKey() {
			this.graph.bindKey(["meta+c", "ctrl+c"], () => {
				const cells = this.graph.getSelectedCells();
				if (cells.length) {
					this.graph.copy(cells);
				}
				return false;
			});
			this.graph.bindKey(["meta+x", "ctrl+x"], () => {
				const cells = this.graph.getSelectedCells();
				if (cells.length) {
					this.graph.cut(cells);
				}
				return false;
			});
			this.graph.bindKey(["meta+v", "ctrl+v"], () => {
				if (!this.graph.isClipboardEmpty()) {
					const cells = this.graph.paste({ offset: 32 });
					this.graph.cleanSelection();
					this.graph.select(cells);
				}
				return false;
			});

			//undo redo
			this.graph.bindKey(["meta+z", "ctrl+z"], () => {
				console.log(this.graph.history);
				if (this.graph.history.canUndo()) {
					this.graph.history.undo();
				}
				return false;
			});
			this.graph.bindKey(["meta+shift+z", "ctrl+shift+z"], () => {
				console.log(this.graph.history);
				if (this.graph.history.canRedo()) {
					this.graph.history.redo();
				}
				return false;
			});

			// select all
			this.graph.bindKey(["meta+a", "ctrl+a"], () => {
				const nodes = this.graph.getNodes();
				if (nodes) {
					this.graph.select(nodes);
				}
			});

			//delete
			this.graph.bindKey("backspace", () => {
				const cells = this.graph.getSelectedCells();
				if (cells.length) {
					this.graph.removeCells(cells);
				}
			});

			// zoom
			this.graph.bindKey(["alt+1", "meta+1"], () => {
				console.log("alt+1");

				const zoom = this.graph.zoom();
				if (zoom < 1.5) {
					this.graph.zoom(0.1);
				}
			});
			this.graph.bindKey(["alt+2", "meta+2"], () => {
				const zoom = this.graph.zoom();
				if (zoom > 0.5) {
					this.graph.zoom(-0.1);
				}
			});
		},
		bindingEvent() {
			// 控制连接桩显示/隐藏
			const showPorts = (ports, show) => {
				for (let i = 0, len = ports.length; i < len; i = i + 1) {
					ports[i].style.visibility = show ? "visible" : "hidden";
				}
			};

			this.graph.on("node:mouseenter", () => {
				const container = document.getElementById("graph-container");
				const ports = container.querySelectorAll(".x6-port-body");
				showPorts(ports, true);
			});
			this.graph.on("node:mouseleave", () => {
				const container = document.getElementById("graph-container");
				const ports = container.querySelectorAll(".x6-port-body");
				showPorts(ports, false);
			});
			this.graph.on("node:selected", ({ cell }) => {
				console.log("------------------------------");
				console.log(cell);
				// cell.setAttrs({
				//   html: this.html.replace('self-defined', 'self-defined self-defined-active')
				// })

				this.optForNode(cell);
			});
			this.graph.on("node:unselected", ({ cell }) => {
				console.log("cell", cell);
				const container = document.getElementById("graph-container");
				const ports = container.querySelectorAll(".x6-port-body");

				showPorts(ports, false);
				this.unOptForNode(cell);
			});
		},
		action(e) {
			console.log("e", e);

			// if (e == 1) {
			// }
			if (e == 2) {
				// 撤销
			}
			// if (e == 3) {
			// }
			// if (e == 4) {
			// }
			// if (e == 5) {
			// }
			// if (e == 6) {
			// }

			if (e == 7) {
				// 打印
			}

			if (e == 8) {
				// 删除节点
				const cells = this.graph.getSelectedCells();
				if (cells.length) {
					this.graph.removeCells(cells);
				}
			}
			if (e == 9) {
				this.saveDag();
			}
		},
		saveDag() {
			console.log(this.graph.toJSON());
			this.writeFile(JSON.stringify(this.graph.toJSON()), "dagData.json");
			localStorage.setItem("dagData", JSON.stringify(this.graph.toJSON()));
		},
		getNodeById(nodes, id) {
			for (let i in nodes) {
				let node = nodes[i];
				if (node.id == id) {
					return node;
				}
			}
		},
		getEdgeByTargetNode(edges, node_id) {
			for (let i in edges) {
				let edge = edges[i];
				console.log("edge", edge.target.cell);
				console.log("node_id", node_id);
				if (edge.target.cell == node_id) {
					return edge;
				}
				return null;
			}
			return null;
		},
		getChildNode(node, nodes, edges) {
			let child_nodes = [];
			for (let i in edges) {
				let edge = edges[i];
				if (edge.source.cell == node.id) {
					let node = this.getNodeById(nodes, edge.target.cell);
					child_nodes.push(node);
				}
			}
			return child_nodes;
		},
		pushChilds(tree_node, nodes, edges) {
			let childs = this.getChildNode(tree_node.node, nodes, edges);
			for (let i in childs) {
				let node = childs[i];
				let child_tree_node = {
					node: {
						id: node.id,
						value: node.store.data.paramList[0].defaultValue,
						type: node.store.data.paramList[0].type,
					},
					childs: [],
				};
				tree_node.childs.push(child_tree_node);
				this.pushChilds(child_tree_node, nodes, edges);
			}
		},
		sleep(ms) {
			return new Promise((resolve) => setTimeout(resolve, ms));
		},
		async setActiveNode() {
			let activeNodes = this.graph.getNodes();
			console.log(" this.graph.", this.graph, activeNodes);
			let oldNode = null;
			for (let id in activeNodes) {
				let node = activeNodes[id];
				this.graph.unselect(node);
			}
			for (let id in activeNodes) {
				await this.sleep(300);
				if (oldNode != null) {
					this.graph.unselect(oldNode);
				}
				let node = activeNodes[id];
				this.graph.select(node);
				oldNode = node;
			}
		},
		async run() {
			let edges = this.graph.getEdges();
			let nodes = this.graph.getNodes();
			this.setActiveNode();
			if (edges.length == 0) {
				alert("没有找到连线");
				return;
			}
			let edge = edges[0];
			let node = this.getNodeById(nodes, edge.getSource().cell);
			// 找到顶上的Root
			while (edge) {
				edge = this.getEdgeByTargetNode(edges, node.id);
				if (edge) {
					node = this.getNodeById(nodes, edge.getSource().cell);
				}
			}
			let tree_node = {
				node: {
					id: node.id,
					value: node.store.data.paramList[0].defaultValue,
					type: node.store.data.paramList[0].type,
				},
				childs: [],
			};

			//组织树
			this.pushChilds(tree_node, nodes, edges);
			let str_btree = JSON.stringify(tree_node);
			this.writeFile(str_btree, "BTree.json");
			this.saveDag();
			let data = {
				command: "bash /workspace/PyInterface/start.sh",
				//command:'cd /workspace&&>aa.txt',
				game_id: this.experiment_id,
			};
			await execCommandExperiment(data);
		},
		dataURLtoFile(dataurl, filename) {
			//将base64转换为文件
			var arr = dataurl.split(","),
				mime = arr[0].match(/:(.*?);/)[1],
				bstr = atob(arr[1]),
				n = bstr.length,
				u8arr = new Uint8Array(n);
			while (n--) {
				u8arr[n] = bstr.charCodeAt(n);
			}
			return new File([u8arr], filename, { type: mime });
		},
		async writeFile(str_btree, fileName) {
			let data = new FormData();
			let filesFile = this.dataURLtoFile(`data:text/markdown;base64,${Base64.encode(str_btree)}`, fileName);
			let myInfo = await this.$myInfo(this);
			data.append("chunkNumber", 1);
			data.append("totalChunks", 1);
			data.append("repeType", "");
			data.append("filename", filesFile.name);
			data.append("relativePath", "/" + fileName);
			data.append("userId", myInfo.id);
			data.append("type", "workspace");
			data.append("bizId", this.experiment_id);
			data.append("file", new Blob([filesFile]), filesFile.name);

			return await uploadFile(data);
		},

		// 放大
		zoomIn() {
			this.scale += 0.1; // 每次放大增加0.1
		},
		// 缩小
		zoomOut() {
			if (this.scale > 0.1) {
				this.scale -= 0.1; // 每次缩小减少0.1，最小缩放比例为0.1
			}
		},

		// 监听鼠标滚轮事件
		handlerWheel(e) {
			// e.deltaY > 0: 向下滚动
			// e.deltaY < 0: 向上滚动

			if (e.deltaY > 0) {
				// 缩小( scale等于0.2就不允许继续缩小了 )
				if (this.scale.toFixed(1) != 0.2) {
					this.zoomOut();
				}
			} else {
				// 放大( scale等于3.3就不允许继续放大了 )
				if (this.scale.toFixed(1) != 3.3) {
					this.zoomIn();
				}
			}

			// document.querySelectorAll(".x6-graph-svg-viewport")[1].style.transform = `scale(${this.scale})`
		},
	},
};
</script>

<style lang="less" scoped>
@import "./index2.less";

#graph-container {
	
}
</style>
